package com.hq.ims.data.service;

import com.alibaba.excel.util.DateUtils;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.google.common.collect.Maps;
import com.hq.authority.utils.AppUtils;
import com.hq.ims.data.annotation.ChangeRecord;
import com.hq.ims.data.config.verification.VdAdd;
import com.hq.ims.data.config.verification.VdEdit;
import com.hq.ims.data.dao.BusiInfoMapper;
import com.hq.ims.data.entity.*;
import com.hq.ims.data.entityenum.*;
import com.hq.ims.data.utils.ErrMsgConstant;
import com.hq.ims.data.utils.LocalConstant;
import com.hq.ims.data.vo.*;
import com.hq.mybatis.base.BaseService;
import com.hq.mybatis.base.page.RequestPage;
import com.hq.utils.util.*;
import com.hq.web.penum.IBaseEnum;
import com.hq.web.utils.SpringBootValidateUtils;
import io.swagger.annotations.ApiModelProperty;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author 蒋柏平
 * @detail 经营信息管理主表 服务实现类
 * @since 20241025
 */
@Service
public class BaseBusiInfoService extends BaseService<BusiInfoMapper, BusiInfo> {

    @Resource
    private BaseBusiIndustryAssignService baseBusiIndustryAssignService;
    @Resource
    private BaseBusiIndustryCompanyService baseBusiIndustryCompanyService;
    @Resource
    private BaseCompanyService baseCompanyService;
    @Resource
    private BaseBusiRepeatTypeCountDataService baseBusiRepeatTypeCountDataService;
    @Resource
    private BaseBusiRepeatTypeCountService baseBusiRepeatTypeCountService;
    @Resource
    private BaseBusInfoTrackService baseBusInfoTrackService;
    @Resource
    private BaseBusInfoFeedbackService baseBusInfoFeedbackService;
    @Resource
    private BaseBusForewarningSetService baseBusForewarningSetService;
    @Resource
    private BaseDictService baseDictService;
    @Resource
    private BaseAreaService baseAreaService;
    @Resource
    private BaseDictService dictService;
    @Resource
    private BaseBusiChangeService baseBusiChangeService;
    @Resource
    private BaseBusiChangeTimeRecordService baseBusiChangeTimeRecordService;

    //单个行业分配的公司总数量
    private int singleIndustryAssignCompanyCount = 3;

    /**
     * 分页
     */
    public List<BusiInfoMapstruct.BusiInfoVo> getByPage(
            RequestPage page,
            BusiInfoMapstruct.PageSearchVo searchVo
    ) {
        //验证
        LambdaQueryChainWrapper<BusiInfo> lq = this.lambdaQuery();
        //查询条件
        if (Objects.isNull(searchVo.getInfoType())) {
            lq.notIn(BusiInfo::getInfoType, new EnumBusinessTypeStatus[]{EnumBusinessTypeStatus.ExternalStatement, EnumBusinessTypeStatus.BigData});
        } else {
            lq.eq(BusiInfo::getInfoType, searchVo.getInfoType());
        }
        lq.eq(StringUtils.isNotEmpty(searchVo.getOrgId()), BusiInfo::getOrgId, searchVo.getOrgId());
        lq.like(StringUtils.isNotEmpty(searchVo.getPublisher()), BusiInfo::getPublisher, searchVo.getPublisher());
        lq.eq(StringUtils.isNotEmpty(searchVo.getPublisherId()), BusiInfo::getPublisherId, searchVo.getPublisherId());
        lq.like(StringUtils.isNotEmpty(searchVo.getProjectName()), BusiInfo::getProjectName, searchVo.getProjectName());
        if (searchVo.getAppUnaudited() != null && searchVo.getAppUnaudited()) {
            lq.in(BusiInfo::getAuditStatus, new EnumAuditStatus[]{EnumAuditStatus.UnderReview, EnumAuditStatus.CancelAudit});
        } else {
            lq.eq(Objects.nonNull(searchVo.getAuditStatus()), BusiInfo::getAuditStatus, searchVo.getAuditStatus());
        }
        lq.eq(Objects.nonNull(searchVo.getPublishStatus()), BusiInfo::getPublishStatus, searchVo.getPublishStatus());
        lq.eq(Objects.nonNull(searchVo.getAcceptStatus()), BusiInfo::getAcceptStatus, searchVo.getAcceptStatus());
        lq.eq(Objects.nonNull(searchVo.getProjectStage()), BusiInfo::getProjectStage, searchVo.getProjectStage());
        lq.eq(StringUtils.isNotEmpty(searchVo.getProvince()), BusiInfo::getProvinceCode, searchVo.getProvince());
        lq.eq(StringUtils.isNotEmpty(searchVo.getCity()), BusiInfo::getCityCode, searchVo.getCity());
        lq.eq(StringUtils.isNotEmpty(searchVo.getOrgId()), BusiInfo::getOrgId, searchVo.getOrgId());
        lq.ge(Objects.nonNull(searchVo.getRepetitionRate()), BusiInfo::getRepetitionRate, searchVo.getRepetitionRate());
        lq.ge(Objects.nonNull(searchVo.getPublishTimeStart()), BusiInfo::getPublishTime, searchVo.getPublishTimeStart());
        lq.le(Objects.nonNull(searchVo.getPublishTimeEnd()), BusiInfo::getPublishTime, searchVo.getPublishTimeEnd());
        if (searchVo.getRootInformationEnum() != null) {
            if (searchVo.getRootInformationEnum().getCode() == EnumRootInformation.RootInformation.getCode()) {
                lq.eq(BusiInfo::getParentId, StringUtils.FH_ZERO);
            } else if (searchVo.getRootInformationEnum().getCode() == EnumRootInformation.Derivative.getCode()) {
                lq.ne(BusiInfo::getParentId, StringUtils.FH_ZERO);
            }
        }
        //查询上级组织公司下所有项目信息，向下查询
        if (StringUtils.isNotEmpty(searchVo.getParentOrgId())) {
            List<Company> allChildrenCompanyList = baseCompanyService.getAllChildrenCompanyList(searchVo.getParentOrgId(), true);
            List<String> companyIds = new ArrayList<>();
            companyIds.add(searchVo.getParentOrgId());
            if (CollectionUtils.isNotEmpty(allChildrenCompanyList)) {
                companyIds.addAll(allChildrenCompanyList.stream().map(Company::getCompanyId).collect(Collectors.toList()));
            }
            lq.in(BusiInfo::getOrgId, companyIds);
        }
        //自定义sql，正则查询包含任一产业标记项目
        StringBuilder lastSql = new StringBuilder();
        if (CollectionUtils.isNotEmpty(searchVo.getIndustryAssigns())) {
            lastSql.append("and industry_assign regexp '(^|,)(");
            lastSql.append(String.join("|", searchVo.getIndustryAssigns()));
            lastSql.append(")(,|$)'");
        }
        if (Objects.nonNull(searchVo.getOrderBy())) {
            lastSql.append("order by ").append(searchVo.getOrderBy().getSql());
        } else {
            lastSql.append("order by audit_status asc ")
                    .append(", create_date_time desc");
        }
        lq.last(lastSql.toString());
        //执行分页
        lq.page(page);
        List<BusiInfo> dataList = page.getRecords();
        List<BusiInfoMapstruct.BusiInfoVo> voList = BusiInfoMapstruct.INSTANCE.toBusiInfoVoList(dataList);
        //拼接推送公司以及派生信息标签
        voList.forEach(busiInfoVo -> {
            List<BusiIndustryCompany> list = baseBusiIndustryCompanyService.lambdaQuery()
                    .select(BusiIndustryCompany::getCompanyName)
                    .eq(BusiIndustryCompany::getBusiInfoId, busiInfoVo.getBusiInfoId())
                    .list();
            String pushCompany = list.stream().map(BusiIndustryCompany::getCompanyName).distinct().collect(Collectors.joining(","));
            busiInfoVo.setPushCompany(pushCompany);
            busiInfoVo.setRootInformationEnum(StringUtils.isEmpty(busiInfoVo.getParentId()) || "0".equals(busiInfoVo.getParentId()) ? EnumRootInformation.RootInformation : EnumRootInformation.Derivative);
        });
        page.setRecords(voList);
        return voList;
    }

    /**
     * 添加
     */
    @Transactional(rollbackFor = Exception.class)
    public BusiInfo addData(BusiInfoMapstruct.SaveVo vo) {
        //验证
        SpringBootValidateUtils.validate(vo, VdAdd.class);

        //账值新的对象
        BusiInfo entity = new BusiInfo();
        entity.setRepetitionRate(vo.getRepetitionRate());
        entity.setProjectName(vo.getProjectName());
        entity.setInfoType(vo.getInfoType());
        entity.setInfoSource(vo.getInfoSource());
        entity.setProjectAddressName(vo.getProjectAddressName());
        entity.setLongitude(vo.getLongitude());
        entity.setLatitude(vo.getLatitude());
        entity.setProjectStage(vo.getProjectStage());
        entity.setProvince(vo.getProvince());
        entity.setProvinceCode(vo.getProvinceCode());
        entity.setCity(vo.getCity());
        entity.setCityCode(vo.getCityCode());
        entity.setContactPerson(vo.getContactPerson());
        entity.setContactInfomation(vo.getContactInfomation());
        entity.setOwnerCompanyName(vo.getOwnerCompanyName());
        entity.setConstructionName(vo.getConstructionName());
        entity.setOutputScale(vo.getOutputScale());
        entity.setProjectRemark(vo.getProjectRemark());
        entity.setPublisher(vo.getPublisher());
        entity.setPublisherId(vo.getPublisherId());
        entity.setPublishStatus(vo.getPublishStatus());
        entity.setPublishTime(vo.getPublishTime());
        entity.setAuditStatus(vo.getAuditStatus());
        entity.setAuditUserId(vo.getAuditUserId());
        entity.setAuditTime(vo.getAuditTime());
        entity.setAuditRemark(vo.getAuditRemark());
        entity.setAcceptStatus(vo.getAcceptStatus());
        entity.setOrgId(vo.getOrgId());
        entity.setOrgName(vo.getOrgName());
        entity.setParentId(vo.getParentId());
        entity.setRootId(vo.getRootId());
        entity.setIndustryAssign(vo.getIndustryAssign());
        entity.setCompanyDivideIntoRuleValue(vo.getCompanyDivideIntoRuleValue());
        entity.setFundingSource(vo.getFundingSource());
        entity.setTenderClosingDate(vo.getTenderClosingDate());
        entity.setDeadlineForBidding(vo.getDeadlineForBidding());
        entity.setProjectScale(vo.getProjectScale());
        entity.setDurationRequired(vo.getDurationRequired());
        entity.setTenderScope(vo.getTenderScope());
        entity.setQualifications(vo.getQualifications());
        entity.setTenderControlPrice(vo.getTenderControlPrice());
        entity.setBond(vo.getBond());
        entity.setBondEndTime(vo.getBondEndTime());
        entity.setCreateDateTime(vo.getCreateDateTime());
        entity.setUpdateDateTime(vo.getUpdateDateTime());
        entity.setIsDel(vo.getIsDel());
        entity.setCreateUserName(vo.getCreateUserName());
        entity.setUpdateUserName(vo.getUpdateUserName());
        entity.setVersion(vo.getVersion());

        entity.insert();
        return entity;
    }

    /**
     * 编辑
     */
    @Transactional(rollbackFor = Exception.class)
    public BusiInfo editData(BusiInfoMapstruct.SaveVo vo) {
        //验证
        SpringBootValidateUtils.validate(vo, VdEdit.class);

        //账值新的对象
        BusiInfo entity = this.getById(vo.getBusiInfoId());
        ObjectUtils.isNullThrow(entity, "数据不存在");

        entity.setRepetitionRate(vo.getRepetitionRate());
        entity.setProjectName(vo.getProjectName());
        entity.setInfoType(vo.getInfoType());
        entity.setInfoSource(vo.getInfoSource());
        entity.setProjectAddressName(vo.getProjectAddressName());
        entity.setLongitude(vo.getLongitude());
        entity.setLatitude(vo.getLatitude());
        entity.setProjectStage(vo.getProjectStage());
        entity.setProvince(vo.getProvince());
        entity.setProvinceCode(vo.getProvinceCode());
        entity.setCity(vo.getCity());
        entity.setCityCode(vo.getCityCode());
        entity.setContactPerson(vo.getContactPerson());
        entity.setContactInfomation(vo.getContactInfomation());
        entity.setOwnerCompanyName(vo.getOwnerCompanyName());
        entity.setConstructionName(vo.getConstructionName());
        entity.setOutputScale(vo.getOutputScale());
        entity.setProjectRemark(vo.getProjectRemark());
        entity.setPublisher(vo.getPublisher());
        entity.setPublisherId(vo.getPublisherId());
        entity.setPublishStatus(vo.getPublishStatus());
        entity.setPublishTime(vo.getPublishTime());
        entity.setAuditStatus(vo.getAuditStatus());
        entity.setAuditUserId(vo.getAuditUserId());
        entity.setAuditTime(vo.getAuditTime());
        entity.setAuditRemark(vo.getAuditRemark());
        entity.setAcceptStatus(vo.getAcceptStatus());
        entity.setOrgId(vo.getOrgId());
        entity.setOrgName(vo.getOrgName());
        entity.setParentId(vo.getParentId());
        entity.setRootId(vo.getRootId());
        entity.setIndustryAssign(vo.getIndustryAssign());
        entity.setCompanyDivideIntoRuleValue(vo.getCompanyDivideIntoRuleValue());
        entity.setFundingSource(vo.getFundingSource());
        entity.setTenderClosingDate(vo.getTenderClosingDate());
        entity.setDeadlineForBidding(vo.getDeadlineForBidding());
        entity.setProjectScale(vo.getProjectScale());
        entity.setDurationRequired(vo.getDurationRequired());
        entity.setTenderScope(vo.getTenderScope());
        entity.setQualifications(vo.getQualifications());
        entity.setTenderControlPrice(vo.getTenderControlPrice());
        entity.setBond(vo.getBond());
        entity.setBondEndTime(vo.getBondEndTime());
        entity.setCreateDateTime(vo.getCreateDateTime());
        entity.setUpdateDateTime(vo.getUpdateDateTime());
        entity.setIsDel(vo.getIsDel());
        entity.setCreateUserName(vo.getCreateUserName());
        entity.setUpdateUserName(vo.getUpdateUserName());
        entity.setVersion(vo.getVersion());

        entity.updateById();
        return entity;
    }


    /**
     * 删除
     */
    @Transactional(rollbackFor = Exception.class)
    public void delByBusiInfoId(String busiInfoId) {
        //验证数据是否存在
        ObjectUtils.isNullThrow(busiInfoId, ErrMsgConstant.PROJECT_INFO_NOT_EXITS);
        BusiInfo entity = this.getById(busiInfoId);
        ObjectUtils.isNullThrow(entity, ErrMsgConstant.PROJECT_INFO_NOT_EXITS);
        //验证数据状态
        BooleanUtils.isFalseThrow(entity.getAuditStatus() != EnumAuditStatus.CancelAudit, "数据只有撤回后才可以删除");
//        EnumAuditStatus.isCanDelTh(entity.getAuditStatus());
        //验证数据是否属于当前用户
        BooleanUtils.isFalseThrow(AppUtils.getUserId().equals(entity.getPublisherId()), ErrMsgConstant.DATA_PERMISSION_LIMIT);
        entity.deleteById();
        //删除指定的类型
        baseBusiIndustryAssignService.lambdaUpdate().eq(BusiIndustryAssign::getBusiInfoId, busiInfoId).remove();
        //删除随机的公司
        baseBusiIndustryCompanyService.lambdaUpdate().eq(BusiIndustryCompany::getBusiInfoId, busiInfoId).remove();
        //删除重复率
        baseBusiRepeatTypeCountService.delByBusiId(entity.getBusiInfoId());
        //删除重复详情
        baseBusiRepeatTypeCountDataService.delByBusiId(entity.getBusiInfoId());
        //删除变更
        baseBusiChangeService.delByBusiId(entity.getBusiInfoId());
        //删除变更时间
        baseBusiChangeTimeRecordService.delByBusiId(entity.getBusiInfoId());
    }

    /**
     * 获取原始数据详情
     */
    public BusiInfoMapstruct.BusiInfoVo getDetailVo(String busiInfoId) {
        //验证数据是否存在
        ObjectUtils.isNullThrow(busiInfoId, ErrMsgConstant.PROJECT_INFO_NOT_EXITS);
        BusiInfo entity = this.getById(busiInfoId);
        ObjectUtils.isNullThrow(entity, ErrMsgConstant.PROJECT_INFO_NOT_EXITS);
        BusiInfoMapstruct.BusiInfoVo vo = BusiInfoMapstruct.INSTANCE.toBusiInfoVo(entity);
        //设置派生/源信息标签
        vo.setRootInformationEnum(StringUtils.isNotEmpty(vo.getParentId()) || "0".equals(vo.getParentId()) ? EnumRootInformation.RootInformation : EnumRootInformation.Derivative);
        //拼接重复信息数据
        List<BusiRepeatTypeCount> list = baseBusiRepeatTypeCountService.lambdaQuery()
                .select(BusiRepeatTypeCount::getRepeatCount, BusiRepeatTypeCount::getRepeatType, BusiRepeatTypeCount::getMaxSimilarityRate)
                .eq(BusiRepeatTypeCount::getBusiInfoId, vo.getBusiInfoId())
                .list();
        list.forEach(busiRepeatTypeCount -> {
            switch (busiRepeatTypeCount.getRepeatType()) {
                case Owner:
                    vo.setOwnerRepeatCount(busiRepeatTypeCount.getRepeatCount());
                    vo.setOwnerRepeatRate(busiRepeatTypeCount.getMaxSimilarityRate());
                    break;
                case Construction:
                    vo.setConstructionRepeatCount(busiRepeatTypeCount.getRepeatCount());
                    vo.setConstructionRepeatRate(busiRepeatTypeCount.getMaxSimilarityRate());
                    break;
                case ProjectName:
                    vo.setNameRepeatCount(busiRepeatTypeCount.getRepeatCount());
                    vo.setNameRepeatRate(busiRepeatTypeCount.getMaxSimilarityRate());
                    break;
                case ProjectAddress:
                    vo.setPlaceRepeatCount(busiRepeatTypeCount.getRepeatCount());
                    vo.setPlaceRepeatRate(busiRepeatTypeCount.getMaxSimilarityRate());
                    break;
                default:
                    break;
            }
        });
        //拼接产业标记
        List<BusiIndustryAssign> assigns = baseBusiIndustryAssignService.lambdaQuery()
                .eq(BusiIndustryAssign::getBusiInfoId, busiInfoId)
                .list();
        vo.setBusiIndustryAssignList(BusiIndustryAssignMapstruct.INSTANCE.toBusiIndustryAssignVoList(assigns));
        vo.getBusiIndustryAssignList().forEach(assign -> {
            //接收预警结束时间
            if (EnumReceiveStatus.UnReceive.getCode() == assign.getReceiveStatus().getCode()) {
                int receiveHour = baseBusForewarningSetService.getHourByEnumFeedbackPhase(EnumFeedbackPhase.PairingNotAgree);
                assign.setForewarningEndDate(entity.getPublishTime().plusHours(receiveHour));
            }
            //拼接推送公司及接收信息
            baseBusiIndustryCompanyService.montageCompany(assign);
            //经营人员跟踪信息
            BusInfoTrack busInfoTrack = baseBusInfoTrackService.lambdaQuery()
                    .eq(BusInfoTrack::getBusiInfoId, busiInfoId)
                    .eq(BusInfoTrack::getIndustryMarkId, assign.getIndustryId())
                    .one();
            assign.setBusInfoTrack(BusInfoTrackMapstruct.INSTANCE.toBusInfoTrackVo(busInfoTrack));
            //本阶段预警结束时间
            if (busInfoTrack != null) {
                int feedbackHour = baseBusForewarningSetService.getHourByEnumFeedbackPhase(busInfoTrack.getLastNewFeedbackPhase());
                assign.setFeedbackEndDate(busInfoTrack.getLastNewFeedbackDate() != null ? busInfoTrack.getLastNewFeedbackDate().plusHours(feedbackHour) : busInfoTrack.getCreateDateTime().plusHours(feedbackHour));
            }
            // 拼接反馈情况列表
            baseBusInfoFeedbackService.montageFeedBack(assign);
        });
        return vo;
    }

    /**
     * 计算相拟率
     *
     * @param oriData       需要比较的数据
     * @param otherDataList 被比较的数据列表
     * @param ruleMap       规则列表,key为比较类型,value为权重占比
     * @param supplier      计算完后需要处理的方法(1:总体数据,2最高相似度的数据)
     * @return 返回总体计算值
     */
    public BigDecimal calcSimilarity(
            BusiInfoMapstruct.CalcSimilarityDataObj oriData,
            List<BusiInfoMapstruct.CalcSimilarityDataObj> otherDataList,
            Map<EnumBusinessRepeatType, BigDecimal> ruleMap,
            BiConsumer<List<BusiInfoMapstruct.CalcSimilarityDataResult>, BusiInfoMapstruct.CalcSimilarityDataResult> supplier
    ) {
        //查找去重需要过滤芯的关链字
        List<Dict> busiRepeatFilterDictList = baseDictService.lambdaQuery().eq(Dict::getRootId, LocalConstant.FILTER_KEY).list();
        Map<String, List<Dict>> busiRepeatFilterDictMap = busiRepeatFilterDictList.stream().filter(d -> d.getLv() > 2).collect(Collectors.groupingBy(d -> d.getParentId()));

        //声明比较结果
        List<BusiInfoMapstruct.CalcSimilarityDataResult> similarityRateList = new ArrayList<>(otherDataList.size());
        //开始比较
        for (BusiInfoMapstruct.CalcSimilarityDataObj otherData : otherDataList) {
            String beCompareDataId = otherData.getBusiInfoId();

            //声明这条数据的比较结果
            BusiInfoMapstruct.CalcSimilarityDataResult calcSimilarityDataResult = new BusiInfoMapstruct.CalcSimilarityDataResult();
            similarityRateList.add(calcSimilarityDataResult);
            calcSimilarityDataResult.setResultTypeList(new ArrayList<>(ruleMap.size()));
            //构造
            calcSimilarityDataResult.setBeCompareDataId(beCompareDataId);

            //以规则开始循环字段相似率
            ruleMap.forEach((enumBusinessRepeatType, typeWeight) -> {
                //字段要比较的值
                String compareValue = StringUtils.EMPTY;
                //字段被比较的值
                String beCompareValue = StringUtils.EMPTY;
                switch (enumBusinessRepeatType) {
                    case Construction:
                        compareValue = oriData.getConstructionName();
                        beCompareValue = otherData.getConstructionName();
                        break;
                    case ProjectName:
                        compareValue = oriData.getProjectName();
                        beCompareValue = otherData.getProjectName();
                        break;
                    case Owner:
                        compareValue = oriData.getOwnerCompanyName();
                        beCompareValue = otherData.getOwnerCompanyName();
                        break;
                    case ProjectAddress:
                        compareValue = oriData.getProjectAddressName();
                        beCompareValue = otherData.getProjectAddressName();
                        break;
                    default:
                        break;
                }
                //比较方的值如果为空则不参与比较,也不参与计算
                if (StringUtils.isNotEmpty(compareValue)) {
                    List<Dict> ruleFilterDictList = busiRepeatFilterDictMap.get(enumBusinessRepeatType.getDictRepeatFilterKey());
                    if (ListUtils.isExistsEle(ruleFilterDictList)) {
                        //在比较值中过滤掉关链字
                        List<String> keyWordFilterList = ruleFilterDictList.stream().map(Dict::getName).distinct().collect(Collectors.toList());
                        compareValue = highlight(keyWordFilterList, compareValue, StringUtils.EMPTY);
                        beCompareValue = highlight(keyWordFilterList, beCompareValue, StringUtils.EMPTY);
                    }

                    //字段占比权重
                    BigDecimal filedSetWeight = BigDecimalUtil.divide(typeWeight, BigDecimalUtil.newBigDecimal("10"));
                    //字段相似度
                    BigDecimal fieldSimilarityRate = BigDecimalUtil.newBigDecimal(StringUtils.similarityPercent(compareValue, beCompareValue)).multiply(BigDecimalUtil.newBigDecimal("100"));

                    BusiInfoMapstruct.CalcSimilarityDataASurnameTypeResult calcSimilarityDataASurnameTypeResult = new BusiInfoMapstruct.CalcSimilarityDataASurnameTypeResult();
                    calcSimilarityDataResult.getResultTypeList().add(calcSimilarityDataASurnameTypeResult);
                    calcSimilarityDataASurnameTypeResult.setBeCompareDataId(beCompareDataId);
                    calcSimilarityDataASurnameTypeResult.setCalcRepeatType(enumBusinessRepeatType);
                    calcSimilarityDataASurnameTypeResult.setBeCompareDataValue(beCompareValue);
                    calcSimilarityDataASurnameTypeResult.setCompareValue(compareValue);
                    calcSimilarityDataASurnameTypeResult.setSimilarityRate(fieldSimilarityRate);
                    calcSimilarityDataASurnameTypeResult.setWeight(filedSetWeight);
                    calcSimilarityDataASurnameTypeResult.setWeightSimilarityRate(fieldSimilarityRate.multiply(filedSetWeight));
                }
            });

            //这条数据下的总相似度
            BigDecimal rowDataRuleTotalSimilarityRate = ListUtils.sumBigDecimal(calcSimilarityDataResult.getResultTypeList(), BusiInfoMapstruct.CalcSimilarityDataASurnameTypeResult::getWeightSimilarityRate);
            //总体相拟率
            calcSimilarityDataResult.setSimilarityRate(rowDataRuleTotalSimilarityRate);
        }

        //取高最相拟率
        BusiInfoMapstruct.CalcSimilarityDataResult calcSimilarityDataResult = similarityRateList.stream().sorted(Comparator.comparing(BusiInfoMapstruct.CalcSimilarityDataResult::getSimilarityRate).reversed()).collect(Collectors.toList()).get(0);
        //设置消费
        supplier.accept(similarityRateList, calcSimilarityDataResult);
        return calcSimilarityDataResult.getSimilarityRate();
    }

    /**
     * @description: 相似率计算参数及结果处理
     * @author: yinzhangxiao
     * @date: 2024/11/15 15:12
     */
    public BigDecimal calcSimilarityRate(BusiInfoMapstruct.SaveVo vo) {
        //拼接原始对比参数
        BusiInfoMapstruct.CalcSimilarityDataObj oriData = new BusiInfoMapstruct.CalcSimilarityDataObj();
        oriData.setOwnerCompanyName(vo.getOwnerCompanyName());
        oriData.setBusiInfoId(vo.getBusiInfoId());
        oriData.setProjectAddressName(vo.getProjectAddressName());
        oriData.setProjectName(vo.getProjectName());
        oriData.setConstructionName(vo.getConstructionName());
        //拼接需要对比的参数
        List<BusiInfo> list = this.lambdaQuery()
                .ne(BusiInfo::getBusiInfoId, vo.getBusiInfoId())
                .list();
        List<BusiInfoMapstruct.CalcSimilarityDataObj> otherDataList = new ArrayList<>(list.size());
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(item -> {
                BusiInfoMapstruct.CalcSimilarityDataObj calcSimilarityDataObj = new BusiInfoMapstruct.CalcSimilarityDataObj();
                calcSimilarityDataObj.setProjectName(item.getProjectName());
                calcSimilarityDataObj.setBusiInfoId(item.getBusiInfoId());
                calcSimilarityDataObj.setConstructionName(item.getConstructionName());
                calcSimilarityDataObj.setOwnerCompanyName(item.getOwnerCompanyName());
                calcSimilarityDataObj.setProjectAddressName(item.getProjectAddressName());
                otherDataList.add(calcSimilarityDataObj);
            });
            //对比规则
            Map<EnumBusinessRepeatType, BigDecimal> ruleMap = Maps.newHashMap();
            ruleMap.put(EnumBusinessRepeatType.Construction, EnumBusinessRepeatType.Construction.getTypeWeight());
            ruleMap.put(EnumBusinessRepeatType.ProjectName, EnumBusinessRepeatType.ProjectName.getTypeWeight());
            ruleMap.put(EnumBusinessRepeatType.Owner, EnumBusinessRepeatType.Owner.getTypeWeight());
            ruleMap.put(EnumBusinessRepeatType.ProjectAddress, EnumBusinessRepeatType.ProjectAddress.getTypeWeight());
            //对比结果处理
            return this.calcSimilarity(oriData, otherDataList, ruleMap, (similarityDataResultList, maxSimilarityRateData) -> {
                List<BusiInfoMapstruct.CalcSimilarityDataASurnameTypeResult> resultList = new ArrayList<>();
                similarityDataResultList.forEach(item -> resultList.addAll(item.getResultTypeList()));
                ruleMap.forEach((enumBusinessRepeatType, typeWeight) -> {
                    BusiRepeatTypeCountMapstruct.SaveVo busiRepeatTypeCountVo = new BusiRepeatTypeCountMapstruct.SaveVo();
                    busiRepeatTypeCountVo.setBusiInfoId(vo.getBusiInfoId());
                    busiRepeatTypeCountVo.setRepeatType(enumBusinessRepeatType);
                    //取对比重复度大于0的数据
                    List<BusiInfoMapstruct.CalcSimilarityDataASurnameTypeResult> repeatTypeList = resultList.stream().filter(item ->
                                    enumBusinessRepeatType.equals(item.getCalcRepeatType()) && item.getSimilarityRate().compareTo(new BigDecimal(0)) > 0)
                            .sorted(Comparator.comparing(BusiInfoMapstruct.CalcSimilarityDataASurnameTypeResult::getSimilarityRate).reversed())
                            .collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(repeatTypeList)) {
                        busiRepeatTypeCountVo.setRepeatCount(repeatTypeList.size());
                        busiRepeatTypeCountVo.setMaxSimilarityRate(BigDecimal.ZERO);
                        if (maxSimilarityRateData != null) {
                            BusiInfoMapstruct.CalcSimilarityDataASurnameTypeResult calcSimilarityDataASurnameTypeResult = maxSimilarityRateData.getResultTypeList().stream().filter(d -> d.getCalcRepeatType() == enumBusinessRepeatType).findFirst().orElse(null);
                            if (calcSimilarityDataASurnameTypeResult != null) {
                                //设置和总复率率相匹配权重百分比
                                busiRepeatTypeCountVo.setMaxSimilarityRate(calcSimilarityDataASurnameTypeResult.getWeightSimilarityRate());
                            }
                        }
                        //删除老数据重新添加
                        List<BusiRepeatTypeCount> oldList = baseBusiRepeatTypeCountService.lambdaQuery()
                                .select(BusiRepeatTypeCount::getBusiRepeatTypeCountId)
                                .eq(BusiRepeatTypeCount::getBusiInfoId, vo.getBusiInfoId())
                                .eq(BusiRepeatTypeCount::getRepeatType, enumBusinessRepeatType)
                                .list();
                        if (CollectionUtils.isNotEmpty(oldList)) {
                            List<String> oldIds = oldList.stream().map(BusiRepeatTypeCount::getBusiRepeatTypeCountId).collect(Collectors.toList());
                            baseBusiRepeatTypeCountService.lambdaUpdate().in(BusiRepeatTypeCount::getBusiRepeatTypeCountId, oldIds).remove();
                            baseBusiRepeatTypeCountDataService.lambdaUpdate().in(BusiRepeatTypeCountData::getBusiRepeatTypeCountId, oldIds).remove();
                        }
                        BusiRepeatTypeCount busiRepeatTypeCount = baseBusiRepeatTypeCountService.addData(busiRepeatTypeCountVo);
                        repeatTypeList.forEach(item -> {
                            BusiInfo busiInfo = this.getById(item.getBeCompareDataId());
                            List<String> compareValueList = Stream.iterate(0, n -> ++n).limit(item.getCompareValue().length()).map(n -> "" + item.getCompareValue().charAt(n)).distinct().collect(Collectors.toList());
                            //高亮显示
                            switch (enumBusinessRepeatType) {
                                case Construction:
                                    busiInfo.setConstructionName(highlight(compareValueList, busiInfo.getConstructionName(), "<span style='color:red'>$1</span>"));
                                    break;
                                case ProjectName:
                                    busiInfo.setProjectName(highlight(compareValueList, busiInfo.getProjectName(), "<span style='color:red'>$1</span>"));
                                    break;
                                case Owner:
                                    busiInfo.setOwnerCompanyName(highlight(compareValueList, busiInfo.getOwnerCompanyName(), "<span style='color:red'>$1</span>"));
                                    break;
                                case ProjectAddress:
                                    busiInfo.setProjectAddressName(highlight(compareValueList, busiInfo.getProjectAddressName(), "<span style='color:red'>$1</span>"));
                                    break;
                                default:
                                    break;
                            }
                            BusiRepeatTypeCountDataMapstruct.SaveVo build = new BusiRepeatTypeCountDataMapstruct.SaveVo();
                            build.setBusiInfoId(busiInfo.getBusiInfoId());
                            build.setProjectName(busiInfo.getProjectName());
                            build.setOwner(busiInfo.getOwnerCompanyName());
                            build.setConstruction(busiInfo.getConstructionName());
                            build.setProjectAddress(busiInfo.getProjectAddressName());
                            build.setPublishTime(busiInfo.getPublishTime());
                            build.setOutputScale(busiInfo.getOutputScale());
                            build.setBusiRepeatTypeCountId(busiRepeatTypeCount.getBusiRepeatTypeCountId());
                            build.setSimilarityRate(item.getWeightSimilarityRate());
                            baseBusiRepeatTypeCountDataService.addData(build);
                        });
                    }
                });
            });
        }
        return new BigDecimal(0);
    }

    /**
     * @description: 关键字对比高亮显示
     * @author: yinzhangxiao
     * @date: 2024/11/15 15:14
     */
    public static String highlight(List<String> keywordList, String patternstring, String replacement) {
        if (CollectionUtils.isNotEmpty(keywordList)) {
            String keywords = String.join("|", keywordList);
            String regex = "(" + keywords + ")";
            Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
            Matcher matcher = pattern.matcher(patternstring);
            patternstring = matcher.replaceAll(replacement);
        }
        return patternstring;
    }

    /**
     * @description: 根据选择的产业标记拼接产业标记冗余字段
     * @author: yinzhangxiao
     * @date: 2024/11/15 15:14
     */
    public void setBusiIndustryAssign(BusiInfoMapstruct.SaveVo vo) {
        if (CollectionUtils.isNotEmpty(vo.getBusiIndustryAssignList())) {
            List<BusiIndustryAssignMapstruct.SaveVo> busiIndustryAssignList = vo.getBusiIndustryAssignList();
            for (BusiIndustryAssignMapstruct.SaveVo saveVo : busiIndustryAssignList) {
                if (StringUtils.isEmpty(saveVo.getIndustryName())) {
                    if (StringUtils.isEmpty(saveVo.getIndustryId())) {
                        throw new RuntimeException("产业标记错误！");
                    }
                    Dict dict = dictService.getById(saveVo.getIndustryId());
                    ObjectUtils.isNullThrow(dict, "产业标记错误!");
                    saveVo.setIndustryName(dict.getName());
                }
            }
            List<String> industryAssignName = busiIndustryAssignList.stream()
                    .map(BusiIndustryAssignMapstruct.SaveVo::getIndustryName)
                    .collect(Collectors.toList());
            vo.setIndustryAssign(String.join(",", industryAssignName));
        }
    }

    /**
     * @description: 补全产业标记指派公司并保存
     * @author: yinzhangxiao
     * @date: 2024/11/15 15:15
     */
    public void saveBusiIndustryAssignList(BusiInfoMapstruct.SaveVo vo) {
        if (ListUtils.isNotExistsEle(vo.getBusiIndustryAssignList())) {
            return;
        }
        //删除项目旧的数据库产业标记
        baseBusiIndustryAssignService.lambdaUpdate().eq(BusiIndustryAssign::getBusiInfoId, vo.getBusiInfoId()).remove();
        //循环保存对象中的产业标记
        vo.getBusiIndustryAssignList().forEach(assign -> {
            //清空何存对象的id
            assign.setBusiIndustryAssignId(null);
            assign.setBusiInfoId(vo.getBusiInfoId());
            assign.setReceiveStatus(EnumReceiveStatus.UnReceive);
            //保存经营信息的产业标记
            baseBusiIndustryAssignService.addData(assign);
            //如果产业标记下未选中公司那么补全产业标记下的公司并保存,最多3家公司
            List<BusiIndustryCompany> companyList = assign.getBusiIndustryCompanyList();
            Boolean isNeedFillIndustryCompany = companyList.size() > 3;
            BooleanUtils.isTrueThrow(isNeedFillIndustryCompany, "产业标记(" + assign.getIndustryName() + "),指派公司超过3个！");
            //根据公司id分组过滤取出数量大于2的公司名称
            List<String> repeatCompanyNameList = companyList.stream()
                    .collect(Collectors.groupingBy(BusiIndustryCompany::getCompanyId))
                    .values().stream()
                    .filter(group -> group.size() > 1)
                    .flatMap(Collection::stream)
                    .collect(Collectors.toList()).stream()
                    .map(BusiIndustryCompany::getCompanyName)
                    .distinct()
                    .collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(repeatCompanyNameList)) {
                BooleanUtils.isTrueThrow(Boolean.TRUE, "产业标记(" + assign.getIndustryName() + "),有重复指派公司(" + repeatCompanyNameList.get(0) + ")!");
            }
            companyList.forEach(company -> {
                company.setBusiIndustryCompanyId(null);
                company.setBusiInfoId(vo.getBusiInfoId());
                company.setIndustryId(assign.getIndustryId());
                company.setIndustryName(assign.getIndustryName());
                if (company.getNotificationWay() == null) {
                    company.setNotificationWay(EnumNotificationWay.Userspecified);
                }
            });
            //是否存在用户指定的公司
            boolean ifUserSpecified = companyList.stream().anyMatch(b -> b.getNotificationWay() == EnumNotificationWay.Userspecified);
            if (CollectionUtils.isEmpty(companyList) || !ifUserSpecified) {
                List<String> companyIds = companyList.stream().map(BusiIndustryCompany::getCompanyId).collect(Collectors.toList());
                int count = CollectionUtils.isEmpty(companyIds) ? singleIndustryAssignCompanyCount : singleIndustryAssignCompanyCount - companyIds.size();
                if (count > 0) {
                    //根据服务地区、产业标记查询所有包含公司
                    CompanyMapstruct.PageSearchVo companySearchVo = new CompanyMapstruct.PageSearchVo();
                    companySearchVo.setCityCode(vo.getCityCode());
                    companySearchVo.setProvinceCode(vo.getProvinceCode());
                    companySearchVo.setServiceTypeId(assign.getIndustryId());
                    List<CompanyMapstruct.CompanyVo> companyVoList = baseCompanyService.getCompanyListByAreaAndServiceType(companySearchVo);
                    //剔除用户指定公司
                    List<CompanyMapstruct.CompanyVo> resultList = companyVoList.stream().filter(companyVo -> !companyIds.contains(companyVo.getCompanyId())).collect(Collectors.toList());
                    //打乱顺序随机
                    Collections.shuffle(resultList);
                    int resultCount = 0;
                    for (CompanyMapstruct.CompanyVo companyVo : resultList) {
                        //补全缺少的数量
                        if (resultCount < count) {
                            BusiIndustryCompany company = new BusiIndustryCompany();
                            company.setCompanyId(companyVo.getCompanyId());
                            company.setBusiInfoId(vo.getBusiInfoId());
                            company.setCompanyName(companyVo.getCompanyName());
                            company.setIndustryId(assign.getIndustryId());
                            company.setIndustryName(assign.getIndustryName());
                            company.setNotificationWay(EnumNotificationWay.Sysgenerated);
                            companyList.add(company);
                        }
                        resultCount++;
                    }
                }
            }
            //删除行业标记下的公司
            baseBusiIndustryCompanyService.lambdaUpdate()
                    .eq(BusiIndustryCompany::getBusiInfoId, vo.getBusiInfoId())
                    .eq(BusiIndustryCompany::getIndustryId, assign.getIndustryId())
                    .remove();
            //保存行业下的公司
            if (CollectionUtils.isNotEmpty(companyList)) {
                baseBusiIndustryCompanyService.saveBatch(companyList);
            }
        });
    }

    /**
     * 根据企业id查询项目备案信息
     *
     * @param companyId typeStatus
     * @return List<BusiInfo>
     */
    public List<BusiInfo> getCompanyBusiInfoList(String companyId, EnumBusinessTypeStatus typeStatus) {
        return this.lambdaQuery().eq(BusiInfo::getInfoType, typeStatus).eq(BusiInfo::getOrgId, companyId).orderByDesc(BusiInfo::getCreateDateTime).list();
    }

    /**
     * @description: 经营信息接收详情
     * @author: yinzhangxiao
     * @date: 2024/11/15 15:23
     */
    public List<BusiIndustryAssignMapstruct.BusiIndustryAssignVo> getReceiveData(String busiInfoId) {
        //拼接产业标记
        List<BusiIndustryAssign> assigns = baseBusiIndustryAssignService.lambdaQuery()
                .eq(BusiIndustryAssign::getBusiInfoId, busiInfoId)
                .list();
        List<BusiIndustryAssignMapstruct.BusiIndustryAssignVo> busiIndustryAssignVoList = BusiIndustryAssignMapstruct.INSTANCE.toBusiIndustryAssignVoList(assigns);
        busiIndustryAssignVoList.forEach(assign -> baseBusiIndustryCompanyService.montageCompany(assign));
        return busiIndustryAssignVoList;
    }

    /**
     * @description: 经营信息反馈详情
     * @author: yinzhangxiao
     * @date: 2024/11/15 15:23
     */
    public List<BusiIndustryAssignMapstruct.BusiIndustryAssignVo> getFeedBackData(String busiInfoId) {
        //拼接产业标记
        List<BusiIndustryAssign> assigns = baseBusiIndustryAssignService.lambdaQuery()
                .eq(BusiIndustryAssign::getBusiInfoId, busiInfoId)
                .list();
        List<BusiIndustryAssignMapstruct.BusiIndustryAssignVo> busiIndustryAssignVoList = BusiIndustryAssignMapstruct.INSTANCE.toBusiIndustryAssignVoList(assigns);
        busiIndustryAssignVoList.forEach(assign -> baseBusInfoFeedbackService.montageFeedBack(assign));
        return busiIndustryAssignVoList;
    }

    /**
     * @description: 经营信息反馈详情
     * @author: yinzhangxiao
     * @date: 2024/12/02 15:23
     */
    public void setAreaCode(BusiInfoMapstruct.SaveVo vo) {
        //查询省份Code
        Area province = baseAreaService.getDetailByNameAndParentId(vo.getProvince(), "0");
        ObjectUtils.isNullThrow(province, ErrMsgConstant.AREA_ERROR);
        vo.setProvinceCode(province.getAreaId());
        //查询市区
        Area city = baseAreaService.getDetailByNameAndParentId(vo.getCity(), province.getAreaId());
        ObjectUtils.isNullThrow(city, ErrMsgConstant.AREA_ERROR);
        vo.setCityCode(city.getAreaId());
    }


    public void validate(BusiInfo entity, BusiInfoMapstruct.SaveVo vo, String method) {
        if (vo.getProjectStage().getCode() == EnumProjectPhase.BidTender.getCode()) {
            if (ObjectUtils.isNull(vo.getTenderClosingDate())) {
                throw new RuntimeException("招标阶段，招标获取截止时间不能为空！");
            }
            if (ObjectUtils.isNull(vo.getDeadlineForBidding())) {
                throw new RuntimeException("招标阶段，招标截止时间不能为空！");
            }
            if (org.apache.commons.lang3.StringUtils.isBlank(vo.getQualifications())) {
                throw new RuntimeException("招标阶段，资质要求不能为空！");
            }
        }
        if (LocalConstant.EDIT.equals(method)) {
            //验证数据状态
            if (vo.getInfoType().getCode() == EnumBusinessTypeStatus.BigData.getCode()) {
                //大数据采集：校验发布状态 已发布状态不能修改
                Boolean publishStatusFlag = EnumPublishStatus.Released.getCode() == entity.getPublishStatus().getCode();
                BooleanUtils.isTrueThrow(publishStatusFlag, ErrMsgConstant.PROJECT_INFO_PUBLISH_STATUS_EXCEPTION);
            } else if (vo.getInfoType().getCode() == EnumBusinessTypeStatus.ExternalStatement.getCode()) {
                //项目备案：校验否存在派生信息 存在派生信息不能修改
                Boolean deriveFlag = super.lambdaQuery().eq(BusiInfo::getParentId, vo.getBusiInfoId()).count() > 0;
                BooleanUtils.isTrueThrow(deriveFlag, ErrMsgConstant.EXITS_DERIVE_DATA);
            } else {
                //全名经营和产业链关联：校验数据状态 审核中 或者 已审核通过并且接收状态不是已拒绝 的数据不能修改
                Boolean editFlag = entity.getAuditStatus().getCode() == EnumAuditStatus.UnderReview.getCode() ||
                        (entity.getAuditStatus().getCode() == EnumAuditStatus.Pass.getCode() && EnumReceiveStatus.Rejection.getCode() != entity.getAcceptStatus().getCode());
                BooleanUtils.isTrueThrow(editFlag, ErrMsgConstant.PROJECT_INFO_PASS);
            }

        }
    }

    public List<Map<String, Object>> compareFields(Object obj1, Object obj2) {
        try {
            List<Map<String, Object>> changeList = new ArrayList<>();
            if (obj1.getClass() == obj2.getClass()) {// 只有两个对象都是同一类型的才有可比性
                Class clazz = obj1.getClass();
                List<Field> fields = Arrays.stream(clazz.getDeclaredFields()).filter(d -> d.isAnnotationPresent(ChangeRecord.class) && d.getAnnotation(ChangeRecord.class).value()).collect(Collectors.toList());
                for (Field field : fields) {
                    Map<String, Object> changeMap = new HashMap<>();
                    field.setAccessible(true);
                    //获取字段值
                    Object oldObj = field.get(obj1);
                    Object newObj = field.get(obj2);
                    //获得注解值
                    String name = field.getAnnotation(ApiModelProperty.class).value();
                    if (oldObj == null && newObj == null) {
                        continue;
                    }
                    if (oldObj instanceof IBaseEnum) {
                        oldObj = ((IBaseEnum) oldObj).getValue();
                    }
                    if (newObj instanceof IBaseEnum) {
                        newObj = ((IBaseEnum) newObj).getValue();
                    }
                    //时间类型处理，精确到年月日时分秒
                    if (oldObj instanceof LocalDateTime) {
                        oldObj = LocalDateTimeUtils.toStr((LocalDateTime) oldObj, LocalDateTimeUtils.DATE_FORMAT_YYYY_MM_DD_HH_MM_SS);
                    }
                    if (newObj instanceof LocalDateTime) {
                        newObj = LocalDateTimeUtils.toStr((LocalDateTime) newObj, LocalDateTimeUtils.DATE_FORMAT_YYYY_MM_DD_HH_MM_SS);
                    }
                    if (oldObj instanceof LocalDate) {
                        oldObj = LocalDateUtils.toStr((LocalDate) oldObj, LocalDateUtils.YMD_PATTERN_YY_MM_DD);
                    }
                    if (newObj instanceof LocalDate) {
                        newObj = LocalDateUtils.toStr((LocalDate) newObj, LocalDateUtils.YMD_PATTERN_YY_MM_DD);
                    }
                    if (oldObj instanceof Date) {
                        oldObj = DateUtils.format((Date) oldObj, LocalDateTimeUtils.DATE_FORMAT_YYYY_MM_DD_HH_MM_SS);
                    }
                    if (newObj instanceof Date) {
                        newObj = DateUtils.format((Date) newObj, LocalDateTimeUtils.DATE_FORMAT_YYYY_MM_DD_HH_MM_SS);
                    }
                    //BigDecimal处理
                    if (oldObj instanceof BigDecimal) {
                        oldObj = ((BigDecimal) oldObj).toPlainString();
                    }
                    if (newObj instanceof BigDecimal) {
                        newObj = ((BigDecimal) newObj).setScale(2, RoundingMode.HALF_UP).toPlainString();
                    }
                    //字符序列处理，null和""默认相等
                    if (oldObj instanceof CharSequence || newObj instanceof CharSequence) {
                        if ((ObjectUtils.isNull(oldObj) || StringUtils.isEmpty(String.valueOf(oldObj))) && (ObjectUtils.isNull(newObj) || StringUtils.isEmpty(String.valueOf(newObj)))) {
                            continue;
                        }
                    }
                    if (ObjectUtils.isNotNull(oldObj) && ObjectUtils.isNotNull(newObj) && oldObj.equals(newObj)) {
                        continue;
                    }
                    changeMap.put("name", name);
                    changeMap.put("changeBefore", oldObj);
                    changeMap.put("changeAfter", newObj);
                    changeList.add(changeMap);
                }
            }
            return changeList;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public void compareIndustry(BusiInfoMapstruct.SaveVo vo, List<Map<String, Object>> maps) {
        //查询原始产业标记以及用户指定公司
        List<BusiIndustryAssign> oldAssignList = baseBusiIndustryAssignService.lambdaQuery().eq(BusiIndustryAssign::getBusiInfoId, vo.getBusiInfoId()).list();
        List<BusiIndustryCompany> oldCompanyList = baseBusiIndustryCompanyService.lambdaQuery().eq(BusiIndustryCompany::getBusiInfoId, vo.getBusiInfoId()).eq(BusiIndustryCompany::getNotificationWay, EnumNotificationWay.Userspecified).list();
        //组装前台推送过来的产业标记以及用户指定公司
        List<BusiIndustryAssignMapstruct.SaveVo> busiIndustryAssignList = vo.getBusiIndustryAssignList();
        List<BusiIndustryCompany> newCompanyList = new ArrayList<>();
        List<BusiIndustryAssign> newAssignList = new ArrayList<>(busiIndustryAssignList.size());
        for (BusiIndustryAssignMapstruct.SaveVo saveVo : busiIndustryAssignList) {
            BusiIndustryAssign busiIndustryAssign = new BusiIndustryAssign();
            BeanUtils.copyProperties(saveVo, busiIndustryAssign);
            newAssignList.add(busiIndustryAssign);
            if (CollectionUtils.isNotEmpty(saveVo.getBusiIndustryCompanyList())) {
                for (BusiIndustryCompany busiIndustryCompany : saveVo.getBusiIndustryCompanyList()) {
                    //指定方式为空或者用户指定为用户指定
                    if (busiIndustryCompany.getNotificationWay() == null || busiIndustryCompany.getNotificationWay().getCode() == EnumNotificationWay.Userspecified.getCode()) {
                        busiIndustryCompany.setIndustryId(saveVo.getIndustryId());
                        busiIndustryCompany.setIndustryName(saveVo.getIndustryName());
                        newCompanyList.add(busiIndustryCompany);
                    }
                }
            }
        }
        //合并产业标记集合（原始数据、更新数据）并根据产业标记id分组判断如果产业标记分组数量等于1则表示有过修改
        long groupIndustryAssign = Stream.concat(oldAssignList.stream(), newAssignList.stream())
                .collect(Collectors.groupingBy(BusiIndustryAssign::getIndustryId, Collectors.counting()))
                .entrySet().stream().filter(e -> e.getValue() == 1)
                .count();
        //合并指定公司集合并根据产业标记id以及公司id分组判断如果分组数量等于1则表示有过修改
        long groupCompany = Stream.concat(oldCompanyList.stream(), newCompanyList.stream())
                .collect(Collectors.groupingBy(BusiIndustryCompany::getIndustryId, Collectors.groupingBy(BusiIndustryCompany::getCompanyId, Collectors.counting())))
                .entrySet().stream()
                .filter(e -> e.getValue().entrySet().stream().anyMatch(d -> d.getValue() == 1))
                .count();
        if (groupIndustryAssign > 0 || groupCompany > 0) {
            //拼接产业标记存库字段
            String changeBefore = getChangeString(oldCompanyList, oldAssignList);
            String changeAfter = getChangeString(newCompanyList, newAssignList);
            Map<String, Object> changeMap = new HashMap<>();
            changeMap.put("name", "产业标记");
            changeMap.put("changeBefore", changeBefore);
            changeMap.put("changeAfter", changeAfter);
            maps.add(changeMap);
        }
    }

    private String getChangeString(List<BusiIndustryCompany> companyList, List<BusiIndustryAssign> assignList) {
        List<BusiIndustryAssignMapstruct.BusiIndustryAssignVo> newVoList = BusiIndustryAssignMapstruct.INSTANCE.toBusiIndustryAssignVoList(assignList);
        StringBuilder changeString = new StringBuilder();
        for (BusiIndustryAssignMapstruct.BusiIndustryAssignVo busiIndustryAssignVo : newVoList) {
            changeString.append(busiIndustryAssignVo.getIndustryName()).append(":");
            List<BusiIndustryCompanyMapstruct.BusiIndustryCompanyVo> collect = companyList.stream().filter(b -> b.getIndustryId().equals(busiIndustryAssignVo.getIndustryId())).map(BusiIndustryCompanyMapstruct.INSTANCE::toBusiIndustryCompanyVo).collect(Collectors.toList());
            changeString.append(collect.stream().map(BusiIndustryCompany::getCompanyName).collect(Collectors.joining("、"))).append("\n");
            busiIndustryAssignVo.setBusiIndustryCompanyList(collect);
        }
        return changeString.toString();
    }
}